#!/usr/bin/env python3
"""
设备配置修复和重启脚本
1. 修复devices.json中的节点ID格式错误
2. 重新启动数据引擎
3. 验证数据连接和读取
"""

import json
import subprocess
import sys
import time
import signal
import os
from datetime import datetime
from pathlib import Path

def fix_device_config():
    """修复设备配置文件中的节点ID格式"""
    print("🔧 修复设备配置文件...")
    
    config_file = Path("config/devices.json")
    
    if not config_file.exists():
        print("❌ 设备配置文件不存在")
        return False
    
    try:
        # 读取当前配置
        with open(config_file, 'r', encoding='utf-8') as f:
            config = json.load(f)
        
        devices = config.get('devices', [])
        print(f"📋 找到 {len(devices)} 个设备")
        
        fixed_count = 0
        for device in devices:
            if device.get('type') != 'opcua':
                continue
            
            device_name = device.get('name', 'Unknown')
            print(f"\n📄 检查设备: {device_name}")
            
            points = device.get('points', [])
            for point in points:
                point_name = point.get('name')
                node_id = point.get('node_id', '')
                
                # 检查是否是Python对象格式
                if 'NodeId(Identifier=' in node_id:
                    print(f"  🔄 修复节点: {point_name}")
                    print(f"    原格式: {node_id}")
                    
                    # 提取标识符和命名空间
                    try:
                        # 简单解析Python对象格式
                        if "Identifier='" in node_id and "NamespaceIndex=" in node_id:
                            # 提取标识符
                            start = node_id.find("Identifier='") + len("Identifier='")
                            end = node_id.find("'", start)
                            identifier = node_id[start:end]
                            
                            # 提取命名空间索引
                            ns_start = node_id.find("NamespaceIndex=") + len("NamespaceIndex=")
                            ns_end = node_id.find(",", ns_start)
                            if ns_end == -1:
                                ns_end = node_id.find(" ", ns_start)
                            namespace = node_id[ns_start:ns_end].strip()
                            
                            # 生成标准格式
                            new_node_id = f"ns={namespace};s={identifier}"
                            point['node_id'] = new_node_id
                            
                            print(f"    新格式: {new_node_id}")
                            fixed_count += 1
                            
                    except Exception as e:
                        print(f"    ❌ 解析失败: {e}")
                        # 手动设置已知的正确节点ID
                        known_mappings = {
                            'H1SP1_ATemp': 'ns=2;s=南湖成套设备.混流泵温度.H1SP1_ATemp',
                            'H1SP1_BTemp': 'ns=2;s=南湖成套设备.混流泵温度.H1SP1_BTemp',
                            'H1SP1_CTemp': 'ns=2;s=南湖成套设备.混流泵温度.H1SP1_CTemp'
                        }
                        
                        if point_name in known_mappings:
                            new_node_id = known_mappings[point_name]
                            point['node_id'] = new_node_id
                            print(f"    新格式: {new_node_id}")
                            fixed_count += 1
                        else:
                            print(f"    ⚠️  未找到已知映射，请手动修复")
        
        if fixed_count > 0:
            # 备份原文件
            backup_file = config_file.parent / f"devices_backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
            import shutil
            shutil.copy2(config_file, backup_file)
            print(f"📦 创建备份: {backup_file}")
            
            # 更新配置
            config['last_updated'] = datetime.now().isoformat()
            
            # 保存修复后的配置
            with open(config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, indent=2, ensure_ascii=False)
            
            print(f"✅ 修复完成，共修复 {fixed_count} 个节点ID")
            return True
        else:
            print("✅ 配置文件格式正确，无需修复")
            return True
            
    except Exception as e:
        print(f"❌ 修复配置文件失败: {e}")
        return False

def kill_existing_processes():
    """终止现有的数据引擎进程"""
    print("\n🔄 检查并终止现有进程...")
    
    try:
        # 查找并终止现有的主进程
        result = subprocess.run(['ps', 'aux'], capture_output=True, text=True)
        lines = result.stdout.split('\n')
        
        killed_count = 0
        for line in lines:
            if 'python' in line and ('main.py' in line or 'start_simple.py' in line):
                # 提取进程ID
                parts = line.split()
                if len(parts) > 1:
                    try:
                        pid = int(parts[1])
                        print(f"  🔫 终止进程 PID {pid}: {' '.join(parts[10:])}")
                        os.kill(pid, signal.SIGTERM)
                        killed_count += 1
                        time.sleep(0.5)
                    except (ValueError, ProcessLookupError, PermissionError) as e:
                        print(f"    ⚠️  无法终止进程 {pid}: {e}")
        
        if killed_count > 0:
            print(f"✅ 终止了 {killed_count} 个进程")
            time.sleep(2)  # 等待进程完全退出
        else:
            print("ℹ️  没有找到需要终止的进程")
            
        return True
        
    except Exception as e:
        print(f"❌ 进程检查失败: {e}")
        return False

def start_data_engine():
    """启动数据引擎"""
    print("\n🚀 启动数据采集引擎...")
    
    try:
        # 选择启动脚本
        if Path("start_simple.py").exists():
            script = "start_simple.py"
        elif Path("main.py").exists():
            script = "main.py"
        else:
            print("❌ 未找到启动脚本")
            return None
        
        print(f"📝 使用启动脚本: {script}")
        
        # 启动进程
        process = subprocess.Popen(
            [sys.executable, script],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            bufsize=1,
            universal_newlines=True
        )
        
        print(f"✅ 数据引擎启动成功，PID: {process.pid}")
        print("⏳ 等待引擎初始化...")
        
        # 等待几秒让引擎初始化
        time.sleep(5)
        
        # 检查进程是否还在运行
        if process.poll() is None:
            print("✅ 数据引擎运行正常")
            return process
        else:
            stdout, stderr = process.communicate()
            print(f"❌ 数据引擎启动失败")
            if stdout:
                print(f"标准输出: {stdout}")
            if stderr:
                print(f"错误输出: {stderr}")
            return None
            
    except Exception as e:
        print(f"❌ 启动数据引擎失败: {e}")
        return None

def test_data_connection():
    """测试数据连接"""
    print("\n🔍 测试数据连接...")
    
    try:
        import requests
        time.sleep(3)  # 等待Web服务启动
        
        # 测试设备列表API
        response = requests.get("http://127.0.0.1:5000/api/devices", timeout=10)
        
        if response.status_code == 200:
            data = response.json()
            if data.get('success'):
                devices = data.get('data', [])
                opcua_devices = [d for d in devices if d.get('type') == 'opcua']
                
                print(f"✅ 设备列表API正常，找到 {len(opcua_devices)} 个OPC UA设备")
                
                # 测试实时数据
                for device in opcua_devices[:1]:  # 只测试第一个设备
                    device_name = device.get('name')
                    print(f"📊 测试设备 {device_name} 的实时数据...")
                    
                    data_response = requests.get(f"http://127.0.0.1:5000/api/device/{device_name}/data", timeout=10)
                    if data_response.status_code == 200:
                        result = data_response.json()
                        if result.get('success'):
                            real_data = result.get('data', [])
                            print(f"  ✅ 获取到 {len(real_data)} 个数据点")
                            
                            # 显示前3个数据点的值
                            for item in real_data[:3]:
                                tag_name = item.get('tag_name')
                                value = item.get('value')
                                quality = item.get('quality')
                                print(f"    📈 {tag_name}: {value} ({quality})")
                            
                            return True
                        else:
                            print(f"  ❌ 实时数据API失败: {result.get('error')}")
                    else:
                        print(f"  ❌ 实时数据API HTTP错误: {data_response.status_code}")
                
                return True
            else:
                print(f"❌ 设备列表API失败: {data.get('error')}")
        else:
            print(f"❌ 设备列表API HTTP错误: {response.status_code}")
        
        return False
        
    except requests.exceptions.ConnectionError:
        print("❌ 无法连接到Web服务器，请检查服务是否启动")
        return False
    except Exception as e:
        print(f"❌ 测试连接失败: {e}")
        return False

def show_usage_instructions():
    """显示使用说明"""
    print("\n" + "=" * 60)
    print("📖 使用说明")
    print("=" * 60)
    print("1. 数据引擎已在后台启动")
    print("2. 请在另一个终端启动Web应用:")
    print("   cd industrial-iot-collector")
    print("   python web/app.py")
    print()
    print("3. 然后访问Dashboard测试实时数据:")
    print("   http://127.0.0.1:5000/dashboard")
    print()
    print("4. 如果需要停止数据引擎:")
    print("   ps aux | grep main.py  # 查找进程ID")
    print("   kill <PID>             # 终止进程")
    print()
    print("5. 调试工具:")
    print("   python test_realtime_data_debug.py  # 数据对比调试")
    print("   python test_dashboard_data_fix.py   # 配置验证")

def main():
    """主函数"""
    print("🚀 设备配置修复和重启工具")
    print("=" * 50)
    
    # 1. 修复设备配置
    if not fix_device_config():
        print("❌ 设备配置修复失败，退出")
        return False
    
    # 2. 终止现有进程
    kill_existing_processes()
    
    # 3. 启动数据引擎
    engine_process = start_data_engine()
    if not engine_process:
        print("❌ 数据引擎启动失败，退出")
        return False
    
    # 4. 测试数据连接
    if test_data_connection():
        print("\n🎉 修复完成！数据引擎已正常运行")
        show_usage_instructions()
        
        # 保持数据引擎运行
        try:
            print("\n⏳ 数据引擎运行中，按 Ctrl+C 停止...")
            engine_process.wait()
        except KeyboardInterrupt:
            print("\n🛑 收到停止信号，正在关闭数据引擎...")
            engine_process.terminate()
            time.sleep(2)
            if engine_process.poll() is None:
                print("强制终止进程...")
                engine_process.kill()
            print("✅ 数据引擎已停止")
        
        return True
    else:
        print("\n❌ 数据连接测试失败")
        print("💡 建议检查:")
        print("  1. OPC UA服务器是否运行在 opc.tcp://127.0.0.1:49320")
        print("  2. 设备配置中的节点ID是否正确")
        print("  3. 网络连接是否正常")
        
        # 停止数据引擎
        if engine_process:
            engine_process.terminate()
        
        return False

if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1) 